package com.xyzwps.paimon.furina.common

import jakarta.servlet.http.Cookie
import org.springframework.web.servlet.function.ServerRequest
import org.springframework.web.servlet.function.ServerResponse

typealias Function<T, R> = (T) -> R
typealias Middleware<T, R> = (T, Function<T, R>) -> R

fun <T, R> f(handle: Function<T, R>, vararg mws: Middleware<T, R>): Function<T, R> {
    if (mws.isEmpty()) {
        return handle
    }
    return mws.foldRight(handle) { mw, next -> { t -> mw(t, next) } }
}


fun hf(
    vararg mws: Middleware<ServerRequest, JsonResponse>,
    handler: RequestHandler
): Function<ServerRequest, ServerResponse> {
    return { req: ServerRequest ->
        try {
            f(handler, *mws)(req).toServerResponse()
        } catch (e: Throwable) {
            wrapError(e, req)
        }
    }
}

typealias RequestHandler = (ServerRequest) -> JsonResponse
typealias RequestFilter = (ServerRequest, RequestHandler) -> JsonResponse

class JsonResponse() {
    private var body: Any? = null
    private val headers: MutableList<Pair<String, Array<out String>>> = ArrayList()
    private val cookies: MutableList<Cookie> = ArrayList()

    fun header(headerName: String, vararg headerValues: String): JsonResponse {
        this.headers.addLast(Pair(headerName, headerValues))
        return this
    }

    fun cookie(cookie: Cookie): JsonResponse {
        this.cookies.addLast(cookie)
        return this
    }

    fun body(body: Any): JsonResponse {
        if (this.body != null) {
            throw IllegalStateException("You write body twice!")
        }
        this.body = body
        return this
    }

    fun toServerResponse(): ServerResponse {
        val b = ServerResponse.ok()
        this.headers.forEach { p -> b.header(p.first, *p.second) }
        this.cookies.forEach(b::cookie)
        return b.body(body ?: OK)
    }
}